import { componentCompileLogger } from './logger/componentCompileLogger';
import * as vscode from 'vscode';
import { spawn } from 'child_process';
import { getRepoPath } from './utils/commonUtils';
import { registerTerminal } from './utils/terminalManager';

export async function syncCode(args: any[]) {
    if (args.length === 0) {
        vscode.window.showErrorMessage('No args provided, please see the log for more information');
        componentCompileLogger.show();
        componentCompileLogger.errorWithStack('No args provided');
        return;
    }

    const uri = args[0] as vscode.Uri;
    if (!uri || typeof uri.fsPath !== 'string') {
        vscode.window.showErrorMessage('Invalid URI provided, , please see the log for more information');
        componentCompileLogger.show();
        componentCompileLogger.errorWithStack('Invalid URI provided');
        return;
    }

    let path = uri.fsPath;
    const fs = require('fs');
    if (fs.existsSync(path) && fs.statSync(path).isDirectory()) {
        path = `${path}/bundle.json`;
        if (!fs.existsSync(path)) {
            vscode.window.showErrorMessage('Could not find bundle.json in the directory, please see the log for more information');
            componentCompileLogger.errorWithStack('Could not find bundle.json in the directory');
            return;
        }
    }
    
    componentCompileLogger.info(`bundle.json's path is : ${path}`);

    const pathParts = path.split(/[/\\]/);
    const parentFolderName = pathParts.length >= 2 ? pathParts.slice(-2, -1)[0] : '';

    if (!parentFolderName) {
        vscode.window.showErrorMessage('Could not extract parent folder name from path, please see the log for more information');
        componentCompileLogger.errorWithStack('Could not extract parent folder name from path');
        return;
    }
    componentCompileLogger.info(`parentFolderName is : ${parentFolderName}`);

    const dirPath = path.substring(0, path.lastIndexOf('/'));
    
    try {
        const { componentName, repoRootPath } = await getComponentName(dirPath, parentFolderName);
        if (!componentName || !repoRootPath) {
            vscode.window.showErrorMessage(`[${parentFolderName}]: Could not get component name. Check logs.`);
            return;
        }
        componentCompileLogger.info(`Component name is ${componentName}, repoRootPath is ${repoRootPath}`);
        vscode.window.showInformationMessage(`[${componentName}]: Sync process has started in the terminal.`);
        executeRepoSync(repoRootPath, componentName);
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : 'Unknown error';
        vscode.window.showErrorMessage(`[${parentFolderName}]: Could not get component name. Check logs.`);
        componentCompileLogger.errorWithStack(errorMessage);
    }
}

/**
 * 执行repo list命令，获取组件名称
 * @param dirPath bundle.json所在目录的全路径
 * @param parentFolderName bundle.json所在目录的父文件夹名称
 * @returns 组件名称
 */
async function getComponentName(dirPath: string, parentFolderName: string): Promise<{ componentName: string, repoRootPath: string }> {
    const repoRootPath = getRepoPath(dirPath);
    if (!repoRootPath) {
        componentCompileLogger.show();
        componentCompileLogger.error('Could not find .repo directory in any parent folder');
        vscode.window.showErrorMessage(`[${parentFolderName}]: Could not find .repo directory`);
        return { componentName: '', repoRootPath: '' };
    }

    // First run repo list to get the component name
    let componentName = parentFolderName;
    const repoListProcess = spawn('repo', ['list'], { cwd: repoRootPath });
    
    let repoListOutput = '';
    
    repoListProcess.stdout.on('data', (data: Buffer) => {
        repoListOutput += data.toString();
    });
    
    // 等待repo list命令执行完成
    return await new Promise<void>((resolve, reject) => {
        repoListProcess.on('close', (code: number) => {
            if (code === 0) {
                resolve();
            } else {
                reject(new Error(`repo list command failed with code ${code}`));
            }
        });
        
        repoListProcess.on('error', (err: Error) => {
            reject(err);
        });
    }).then(() => {
        // Process the repo list output to find the component name
        const lines = repoListOutput.split('\n');
        const relativePath = dirPath.replace(repoRootPath + '/', '');
        
        componentCompileLogger.info(`Looking for component at relative path: ${relativePath}`);
        
        for (const line of lines) {
            // Fix for the correct format: "directory : component_name"
            const parts = line.trim().split(/\s*:\s*/);
            if (parts.length === 2) {
                const path = parts[0].trim();
                const name = parts[1].trim();
                if (path && relativePath.startsWith(path)) {
                    componentName = name;
                    componentCompileLogger.info(`Found component name: ${componentName} for path: ${path}`);
                    break;
                }
            }
        }

        return { componentName: componentName, repoRootPath: repoRootPath };
    }).catch((error: Error) => {
        componentCompileLogger.show();
        componentCompileLogger.errorWithStack(`Failed to get component name from repo list: ${error instanceof Error ? error.message : 'unknown error'}`);
        return { componentName: '', repoRootPath: '' };
    });
}

/**
 * 执行repo sync命令
 * @param repoRootPath .repo目录所在目录
 * @param componentName 组件名称
 */
function executeRepoSync(repoRootPath: string, componentName: string) {
    let commandStr = `repo sync -c build ${componentName}`;
    if (componentName === 'build') {
        commandStr = `repo sync -c build`;
    }
    
    componentCompileLogger.info(`Executing command: ${commandStr} in directory: ${repoRootPath}`);

    const terminal = vscode.window.createTerminal({ name: `Sync Code: ${componentName}`, cwd: repoRootPath });
    registerTerminal('sync', terminal);
    
    terminal.show();
    terminal.sendText(commandStr);
}